package com.yuanrui.interview.server.config.context;

import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 登录上下文对象
 */
public class LonginContextHolder {

    /**
     * ThreadLocal和InheritableThreadLocal的区别：
     * 1. ThreadLocal只能在当前线程中传递值，子线程无法获取到父线程的值，兄弟线程也无法获取到值
     * 2. InheritableThreadLocal可以在子线程中获取到父线程的值，但是只能获取到父线程的值，无法获取到兄弟线程的值
     *      当涉及到线程池的时候，InheritableThreadLocal会有问题，因为线程池中的线程是复用的，可能会导致线程之间的值混乱
     * 3. TransmitThreadLocal可以在子线程中获取到父线程的值，也可以获取到兄弟线程的值
     * @ return 登录信息
     */
//    private static final ThreadLocal<Map<String, Object>> THREAD_LOCAL =
//            new ThreadLocal<>();


    private static final InheritableThreadLocal<Map<String, Object>> INHERITABLE_THREAD_LOCAL =
            new InheritableThreadLocal<>();
//    private static final TransmitThreadLocal<Map<String, Object>> TRANSMIT_THREAD_LOCAL =
//            new TransmitThreadLocal<>();

    public static void set(String key, Object value) {
        Map<String, Object> map = getThreadLocalMap();
        map.put(key, value);
    }

    public static Map<String,Object> getThreadLocalMap() {
        Map<String, Object> map = INHERITABLE_THREAD_LOCAL.get();
        if (Objects.isNull(map)){
            map = new ConcurrentHashMap<>();
            INHERITABLE_THREAD_LOCAL.set(map);
        }
        return map;
    }

    public static Object get(String key) {
        Map<String, Object> map = getThreadLocalMap();
        return map.get(key);
    }

    /*
    ThreadLocal的remove方法是为了防止内存泄漏，因为ThreadLocalMap中的key是弱引用，value是强引用
    ThreadLocal搭配SpringMVC使用时，如果不手动调用remove方法，会导致ThreadLocalMap中的key无法被回收，从而导致内存泄漏
     */
    public static void remove() {
        INHERITABLE_THREAD_LOCAL.remove();
    }

    public static String getLoginId() {
        Map<String, Object> map = getThreadLocalMap();
        return (String) map.get("loginId");
    }
}